﻿using System;
using System.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Text;
using System.Globalization;

namespace Microsoft.Xna.Framework.Content
{
    public sealed class ContentReader : BinaryReader
    {
        private ContentManager contentManager;
        private GraphicsDevice graphicsDevice;
		private string assetName;

        public ContentTypeReader[] TypeReaders
        {
            get;
            set;
        }

        internal GraphicsDevice GraphicsDevice
        {
            get { return this.graphicsDevice; }
        }

        internal ContentReader(ContentManager manager, Stream stream, GraphicsDevice graphicsDevice)
            : base(stream)
        {
            this.graphicsDevice = graphicsDevice;
            this.contentManager = manager;
        }

        public ContentManager ContentManager
        {
            get { return this.contentManager; }
        }


        public T ReadExternalReference<T>()
        {
            throw new NotImplementedException();
        }

        public Matrix ReadMatrix()
        {
            Matrix result = new Matrix();
            result.M11 = ReadSingle();
            result.M12 = ReadSingle();
            result.M13 = ReadSingle();
            result.M14 = ReadSingle();
            result.M21 = ReadSingle();
            result.M22 = ReadSingle();
            result.M23 = ReadSingle();
            result.M24 = ReadSingle();
            result.M31 = ReadSingle();
            result.M32 = ReadSingle();
            result.M33 = ReadSingle();
            result.M34 = ReadSingle();
            result.M41 = ReadSingle();
            result.M42 = ReadSingle();
            result.M43 = ReadSingle();
            result.M44 = ReadSingle();
            return result;
        }

        public T ReadObject<T>()
        {
            int tmp = Read7BitEncodedInt();
            if (tmp == 0) return default(T);
            tmp--;
            return (T)TypeReaders[tmp].Read(this, default(T));
        }

        public T ReadObject<T>(ContentTypeReader typeReader)
        {
            return (T)typeReader.Read(this, default(T));
        }

        public T ReadObject<T>(T existingInstance)
        {
            throw new NotImplementedException();
        }

        public T ReadObject<T>(ContentTypeReader typeReader, T existingInstance)
        {
            return (T)typeReader.Read(this, existingInstance);
        }

        public Quaternion ReadQuaternion()
        {
            throw new NotImplementedException();
        }

        public T ReadRawObject<T>()
        {
            throw new NotImplementedException();
        }

        public T ReadRawObject<T>(ContentTypeReader typeReader)
        {
            throw new NotImplementedException();
        }

        public T ReadRawObject<T>(T existingInstance)
        {
            throw new NotImplementedException();
        }

        public T ReadRawObject<T>(ContentTypeReader typeReader, T existingInstance)
        {
            throw new NotImplementedException();
        }

        public void ReadSharedResource<T>(Action<T> fixup)
        {
            throw new NotImplementedException();
        }

        public Vector2 ReadVector2()
        {
            Vector2 result = new Vector2();
            result.X = ReadSingle();
            result.Y = ReadSingle();
            return result;
        }

        public Vector3 ReadVector3()
        {
            Vector3 result = new Vector3();
            result.X = ReadSingle();
            result.Y = ReadSingle();
            result.Z = ReadSingle();
            return result;
        }

        public Vector4 ReadVector4()
        {
            //FIXME: Test this. Should 'w' be first or last?
            Vector4 result = new Vector4();
            result.X = ReadSingle();
            result.Y = ReadSingle();
            result.Z = ReadSingle();
            result.W = ReadSingle();
            return result;
        }

		internal Exception CreateContentLoadException(string message, params object[] messageArgs)
		{
			return CreateContentLoadException(this.assetName, null, message, messageArgs);
		}

		internal static ContentLoadException CreateContentLoadException(string assetName, Exception innerException, string message, params object[] messageArgs)
		{
			object[] array = new object[messageArgs.Length + 1];
			array[0] = assetName;
			messageArgs.CopyTo(array, 1);
			return new ContentLoadException(string.Format(CultureInfo.CurrentCulture, message, array), innerException);
		}
	}
}
